package me.leon.ext.android

import android.os.Build
import android.text.Html
import android.util.Base64
import androidx.core.text.HtmlCompat
import java.net.URLDecoder
import java.net.URLEncoder
import java.nio.charset.Charset

/**
 * Return the urlencoded string.
 */
fun String.urlEncode(charsetName: String = "UTF-8"): String = URLEncoder.encode(this, charsetName)

/**
 * Return the string of decode urlencoded string.
 */
fun String.urlDecode(charsetName: String = "UTF-8"): String = URLDecoder.decode(this, charsetName)


/**
 * Return Base64-encode bytes.
 *
 */
fun String.base64(charsetName: String = "UTF-8"): ByteArray =
    toByteArray(Charset.forName(charsetName))
        .base64()

/**
 * Return Base64-encode bytes.
 */
fun ByteArray.base64(): ByteArray =
    Base64.encode(this, Base64.NO_WRAP)

/**
 * Return Base64-encode string.
 */
fun ByteArray.base64Encode2String(): String =
    Base64.encodeToString(this, Base64.NO_WRAP)

/**
 * Return the bytes of decode Base64-encode string.
 */
fun String.base64Decode(): ByteArray =
    Base64.decode(this, Base64.NO_WRAP)

/**
 * Return the bytes of decode Base64-encode bytes.
 *
 */
fun ByteArray.base64Decode(): ByteArray =
    Base64.decode(this, Base64.NO_WRAP)

/**
 * Return html-encode string.
 */
fun CharSequence.htmlEncode(): String {
    val sb = StringBuilder()
    var c: Char
    var i = 0
    val len = this.length
    while (i < len) {
        c = this[i]
        when (c) {
            '<' -> sb.append("&lt;") // $NON-NLS-1$
            '>' -> sb.append("&gt;") // $NON-NLS-1$
            '&' -> sb.append("&amp;") // $NON-NLS-1$
            '\'' -> // http://www.w3.org/TR/xhtml1
                // The named character reference &apos; (the apostrophe, U+0027) was
                // introduced in XML 1.0 but does not appear in HTML. Authors should
                // therefore use &#39; instead of &apos; to work as expected in HTML 4
                // user agents.
                sb.append("&#39;") // $NON-NLS-1$
            '"' -> sb.append("&quot;") // $NON-NLS-1$
            else -> sb.append(c)
        }
        i++
    }
    return sb.toString()
}

/**
 * Return the string of decode html-encode string.
 *
 */
fun String.htmlDecode(): CharSequence=
    HtmlCompat.fromHtml(this, HtmlCompat.FROM_HTML_MODE_LEGACY)


/**
 * Return the binary encoded string padded with one space
 */
fun String.binaryEncode() =
        toCharArray()
        .map { Integer.toBinaryString(it.code) + ' ' }
        .fold(StringBuilder()) { acc, s -> acc.append(s) }
        .toString()

/**
 * Return UTF-8 String from binary
 */
fun String.binaryDecode() =
        split(" ".toRegex())
        .toTypedArray()
        .map { it.replace(" ", "").toInt(2).toChar() }
        .fold(StringBuilder()) { acc, c -> acc.append(c) }
        .toString()

